#include "ListaSimple.h"
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#include <stdbool.h>

void ls_Crear(TListaSimple *pLs){
	pLs->Corriente = NULL;
	pLs->Primero = NULL;
	pLs->TamanioLista = 0;
}

void ls_Vaciar(TListaSimple *pLs){
	TNodoSimple *pNodo, *siguiente;
	for(pNodo = pLs->Primero;(pNodo);pNodo=siguiente){
		siguiente = pNodo->Siguiente;
		free(pNodo->Elem);
		free(pNodo);
	}
	pLs->Primero=pLs->Corriente=NULL;
	pLs->TamanioLista = 0;
}

void ls_VaciarLight(TListaSimple *pLs) {
	TNodoSimple *pNodo, *siguiente;
	for(pNodo = pLs->Primero;(pNodo);pNodo=siguiente){
		siguiente = pNodo->Siguiente;
		free(pNodo);
	}
	pLs->Primero=pLs->Corriente=NULL;
	pLs->TamanioLista = 0;
}

int ls_Vacia(TListaSimple Ls){
	return (Ls.Primero == NULL);
}

void ls_ElemCorriente(TListaSimple Ls, void **pE){
	*pE = Ls.Corriente->Elem;
}

int ls_MoverCorriente(TListaSimple *pLs, TMovimiento_Ls M){
	void *aux; //declaro una variable auxiliar

	switch (M){
		case LS_PRIMERO: 
			pLs->Corriente=pLs->Primero;
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			break;
		
		case LS_SIGUIENTE:
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			if (pLs->Corriente->Siguiente==NULL)
				return false;
			else
				pLs->Corriente=pLs->Corriente->Siguiente;
			break;
		
		case LS_ANTERIOR:
			if (pLs->Corriente==NULL)	//se agrega if para saber si la lista esta vacia
				return false;
			if (pLs->Primero==pLs->Corriente)
				return false; //estoy en el primero, no hay anterior
			else{
				aux=pLs->Corriente; //recuerdo cual es la posicion actual
				pLs->Corriente=pLs->Primero; // me paro en el primero
				while (pLs->Corriente->Siguiente!=aux) //me fijo si el siguiente es distinto al que busco
					pLs->Corriente=pLs->Corriente->Siguiente; // entonces paso al siguiente
			}
	}
	return true;
}

void ls_BorrarCorriente(TListaSimple *pLs){
	TNodoSimple *PNodo=pLs->Corriente;
	if (pLs->Corriente==pLs->Primero){
		pLs->Primero = pLs->Corriente->Siguiente;
		pLs->Corriente = pLs->Primero;
	}
	else{
		TNodoSimple *PAux=pLs->Primero;
		while (PAux->Siguiente!=pLs->Corriente)
			PAux = PAux->Siguiente;
		PAux->Siguiente=pLs->Corriente->Siguiente;
		if (PAux->Siguiente) //Si no es el �ltimo
			pLs->Corriente = PAux->Siguiente;
		else
			pLs->Corriente = PAux; //Si es el �ltimo queda en el anterior al borrado
	}
	free(PNodo->Elem);
	free(PNodo);
	pLs->TamanioLista--;
}

void ls_BorrarCorrienteLight(TListaSimple *pLs){
	TNodoSimple *PNodo=pLs->Corriente;
	if (pLs->Corriente==pLs->Primero){
		pLs->Primero = pLs->Corriente->Siguiente;
		pLs->Corriente = pLs->Primero;
	}
	else{
		TNodoSimple *PAux=pLs->Primero;
		while (PAux->Siguiente!=pLs->Corriente)
			PAux = PAux->Siguiente;
		PAux->Siguiente=pLs->Corriente->Siguiente;
		if (PAux->Siguiente) //Si no es el �ltimo
			pLs->Corriente = PAux->Siguiente;
		else
			pLs->Corriente = PAux; //Si es el �ltimo queda en el anterior al borrado
	}
	free(PNodo);
	pLs->TamanioLista--;
}

int ls_Insertar(TListaSimple *pLs, TMovimiento_Ls M, void* pE){
	TNodoSimple *pNodo = (TNodoSimple*) malloc(sizeof(TNodoSimple));
	if (!pNodo)
		return false; //No hay memoria disponible

	if ((pLs->Primero == NULL) || (M==LS_PRIMERO) ||
		((M==LS_ANTERIOR) && (pLs->Primero==pLs->Corriente)))		{
			//Si est� vac�a o hay que insertar en el primero o
			//hay que insertar en el anterior y el actual es el primero
		pNodo->Siguiente = pLs->Primero;
		pLs->Primero = pLs->Corriente = pNodo;
	}
	else{
		if (M == LS_SIGUIENTE){
			pNodo->Siguiente = pLs->Corriente->Siguiente;
			pLs->Corriente->Siguiente = pNodo;
		}
		else{ //LS_ANTERIOR
			TNodoSimple *pAux=pLs->Primero;
			while (pAux->Siguiente!=pLs->Corriente)
				pAux = pAux->Siguiente;
			pAux->Siguiente = pNodo;
			pNodo->Siguiente = pLs->Corriente;
		}
	}
	pNodo->Elem = pE;
	pLs->Corriente=pNodo;
	pLs->TamanioLista++;
	return true;
}

int ls_Tamanio(TListaSimple pLs) {
	return pLs.TamanioLista;
}
